#pragma once
#include "WndItem.h"
#include <Psapi.h>

#include <boost/bimap.hpp>

typedef std::list<WndItemPtr> WndItems;
struct IconCache
{
	HICON AddIconCache(HWND wnd, HICON icon)
	{
		LogDebug("add " + FMTVAR(wnd));
		Cache::iterator it = mCache.find(wnd);
		if (it != mCache.end())
		{
			::DestroyIcon(it->second.second);
		}
		HICON ret = CopyIcon(icon);
		ASSERT(ret);
		mCache.insert(std::make_pair(wnd, std::make_pair(1, ret)));
		return ret;
	};

	void Start()
	{
		for (Cache::iterator it(mCache.begin());
			it != mCache.end(); ++it)
		{
			it->second.first = 0;
		}
	}

	~IconCache()
	{
		for (Cache::iterator it(mCache.begin());
			it != mCache.end(); ++it)
		{
			::DestroyIcon(it->second.second);
		}
	}

	void ClearIcon()
	{
		for (Cache::iterator it(mCache.begin());
			it != mCache.end(); )
		{
			if (it->second.first == 0)
			{
				LogDebug("clear " + FMTVAR(it->second.second))
				::DestroyIcon(it->second.second);
				mCache.erase(it++);
			}
			else
			{
				++it;
			}
		}
	}

	HICON GetIcon(HWND wnd)
	{
		Cache::iterator it = mCache.find(wnd);
		if (it != mCache.end())
		{
			++it->second.first;
			LogDebug("Get " + FMTVAR(it->second.second))
			return it->second.second;
		}
		return NULL;
	}
	typedef std::map<HWND, std::pair<int, HICON>> Cache;
	Cache mCache;
};

class WndInfo
{
public:
	void Add(HWND hwnd);
	HWND Get(const std::wstring appName) const
	{
		AppAndWndMap::left_const_iterator leftIt = mAppAndWndMap.left.find(appName) ;
		if (leftIt == mAppAndWndMap.left.end())
		{
			return NULL;
		}
		return leftIt->second;
	}
private:
	typedef boost::bimap<std::wstring, HWND> AppAndWndMap;
	AppAndWndMap mAppAndWndMap;
};
class WndPrcoessManager
{
public:
	typedef boost::shared_ptr<WndPrcoessManager> Ptr;
	WndPrcoessManager(void);
	~WndPrcoessManager(void);

	WndPrcoessManager::WndItems& GetWndItems() { return mWndItems; }
	bool Refresh();

	static const std::wstring GetProcessName(HWND hwnd);
public:
	void AddWnd(HWND hwnd);
	void RemoveWnd(HWND hwnd);

	void RefreshIcon();
	void RefreshWndInfo();
	static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);
	static BOOL CheckVaildWnd(HWND hwnd);
	HICON GetWindowIcon(HWND hwnd);

	static HICON SendMegGetIcon(HWND hwnd, int iconType);
	static HICON SendMegGetDragIcon(HWND hwnd, int iconType);

	HWND GetProcessName(const std::wstring appName) const;

	WndItems mWndItems;

	WndInfo mWndInfo;
	
	IconCache mIconCache;
	
};
